package com.hhd.pdf.components.innertable;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hhd.pdf.CommonUtils;
import com.hhd.pdf.components.AbstractInLineBlockComponent;
import com.hhd.pdf.components.table.TableBorderHelper;
import com.hhd.pdf.context.GeneratorContext;
import com.hhd.pdf.utils.PdfUtils;
import com.hhd.pdf.variable.DynamicFormula;
import com.hhd.pdf.variable.ParsedFormula;
import com.hhd.pdf.variable.VariableContext;
import com.hhd.pdf.variable.VariablePath;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import org.dom4j.Attribute;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

@Component
public class InnerTable extends AbstractInLineBlockComponent {
    @Override
    public List<Element> createElements(org.dom4j.Element element,
                                        GeneratorContext context,
                                        VariableContext rootVariableContext) throws DocumentException, IOException {
        JSONArray dataSource = getDataSource(element, rootVariableContext);
        if (CommonUtils.isEmpty(dataSource)) return CommonUtils.newList();
        List<InnerColumn> innerColumns = parseColumns(element);
        TableBorderHelper tableBorderHelper = new TableBorderHelper();

        PdfPTable table = createTable(innerColumns, context);
        drawHeader(innerColumns, table, context, tableBorderHelper);

        drawBody(innerColumns, table, context, tableBorderHelper, dataSource);

//        return CommonUtils.newList();
        return CommonUtils.newList(table);
    }

    private void drawBody(List<InnerColumn> innerColumns, PdfPTable table, GeneratorContext context, TableBorderHelper tableBorderHelper, JSONArray dataSource) throws DocumentException, IOException {
        for (int i = 0; i < dataSource.size(); i++) {
            JSONObject jsonObject = dataSource.getJSONObject(i);
            for (InnerColumn innerColumn : innerColumns) {
                if (innerColumn.isBodySlot()) {
                    table.addCell(createCellSlot(context, jsonObject, tableBorderHelper, innerColumn));
                } else {
                    table.addCell(createCell(context, getStringFromJSON(jsonObject, innerColumn), tableBorderHelper));
                }

                tableBorderHelper.nextCol();
            }
            tableBorderHelper.nextRow();
        }
    }

    private String getStringFromJSON(JSONObject jsonObject, InnerColumn innerColumn) {
        if (CommonUtils.isEmpty(jsonObject)) return "";
        VariableContext context = VariableContext.builder()
                .basePath(VariablePath.root())
                .container(jsonObject)
                .build();

        ParsedFormula formula = ParsedFormula.formula(innerColumn.getDataIndex());
        context.execute(formula);

        return formula.getFormulaValue();
//        return jsonObject.getString(innerColumn.getDataIndex());
    }

    private void drawHeader(List<InnerColumn> innerColumns, PdfPTable table, GeneratorContext context, TableBorderHelper tableBorderHelper) {
        for (InnerColumn innerColumn : innerColumns) {
            PdfPCell cell = createCell(context, innerColumn.getTitle(), tableBorderHelper);
            cell.setBackgroundColor(PdfUtils.createColor(250, 250, 250));
            table.addCell(cell);

            tableBorderHelper.nextCol();
        }
        tableBorderHelper.nextRow();
    }


    private PdfPCell createCellSlot(GeneratorContext context, JSONObject jsonObject, TableBorderHelper tableBorderHelper, InnerColumn innerColumn) throws DocumentException, IOException {
        PdfPCell cell = PdfUtils.createCell();
        tableBorderHelper.setBorder(cell, context);
        cell.setPaddingBottom(8);

        List<Element> elements = doCreateCellSlot(context, jsonObject, innerColumn);
        Paragraph paragraph = PdfUtils.createParagraph(context.getGeneratorParameters().getFont(), Paragraph.ALIGN_CENTER);

        if (CommonUtils.isEmpty(elements)) return cell;
        elements.stream().forEach(paragraph::add);
        cell.addElement(paragraph);
        return cell;
    }

    private List<com.itextpdf.text.Element> doCreateCellSlot(GeneratorContext context, JSONObject jsonObject, InnerColumn innerColumn) throws DocumentException, IOException {
        if (CommonUtils.isEmpty(jsonObject)) return CommonUtils.newList();
        VariableContext variableContext = VariableContext.builder()
                .basePath(VariablePath.root())
                .container(jsonObject)
                .build();
        return createPdfElementsByVariableContext(variableContext, innerColumn.getElement(), context);
    }

    private PdfPCell createCell(GeneratorContext context, String content, TableBorderHelper tableBorderHelper) {
        PdfPCell cell = PdfUtils.createCell();
        tableBorderHelper.setBorder(cell, context);
        cell.setPaddingBottom(8);
        Paragraph paragraph = PdfUtils.createParagraph(content, context.getGeneratorParameters().getFont(), Paragraph.ALIGN_CENTER);
        cell.addElement(paragraph);
        return cell;
    }

    private PdfPTable createTable(List<InnerColumn> innerColumns, GeneratorContext context) {
        return PdfUtils.createTable(innerColumns.size(), context.getGeneratorParameters().getPageWidth());
    }

    private LinkedList<InnerColumn> parseColumns(org.dom4j.Element element) {
        List<org.dom4j.Element> elements = element.elements();
        LinkedList<InnerColumn> cols = CommonUtils.newList();
        for (org.dom4j.Element col : elements) {
            if (col.getName().equals("col")) {
                cols.add(new InnerColumn(col));
            }
        }
        return cols;
    }

    private JSONArray getDataSource(org.dom4j.Element element, VariableContext rootVariableContext) {
        Attribute dataSource = element.attribute("dataSource");
        DynamicFormula<JSONArray> formula = DynamicFormula.formula(dataSource.getText().trim(), JSONArray.class);
        rootVariableContext.execute(formula);
        Object o = formula.getFormulaValue();
        JSONArray res = new JSONArray();
        if (CommonUtils.isEmpty(o)) return res;
        if (o instanceof JSONObject) {
            res.add(o);
            return res;
        }
        return formula.getFormulaValue();
    }

    @Override
    public String getName() {
        return "inner-table";
    }
}
